package org.anyline.metadata;

import org.anyline.util.BeanUtil;

import java.util.ArrayList;
import java.util.List;

public class BaseMetadata<T extends BaseMetadata> {

    protected String catalog                      ; // 数据库 catalog与schema 不同有数据库实现方式不一样
    protected String schema                       ; // dbo mysql中相当于数据库名  查数据库列表 是用SHOW SCHEMAS 但JDBC con.getCatalog()返回数据库名 而con.getSchema()返回null
    protected String name                         ; // 名称
    protected String comment                      ; // 备注
    protected Long objectId;

    protected Table table;
    protected String definition;

    protected T origin;
    protected T update;
    protected boolean setmap = false              ;  //执行了upate()操作后set操作是否映射到update上(除了table,catalog, schema,name,drop,action)
    protected boolean getmap = false              ;  //执行了upate()操作后get操作是否映射到update上(除了table,catalog, schema,name,drop,action)

    protected boolean drop = false                ;
    protected String action = null                ; //ddl命令 add drop alter
    protected List<String> ddls                   ;
    public String getCatalog() {
        return catalog;
    }

    public T setCatalog(String catalog) {
        this.catalog = catalog;
        return (T)this;
    }

    public String getSchema() {
        return schema;
    }

    public T setSchema(String schema) {
        this.schema = schema;
        return (T)this;
    }

    public String getName() {
        return name;
    }

    public T setName(String name) {
        this.name = name;
        return (T)this;
    }

    public T setComment(String comment) {
        if(setmap && null != update){
            update.comment = comment;
            return (T)this;
        }
        this.comment = comment;
        return (T)this;
    }


    public String getComment() {
        if(getmap && null != update){
            return update.comment;
        }
        return comment;
    }

    public T delete() {
        this.drop = true;
        return (T)this;
    }

    public boolean isDelete() {
        return drop;
    }


    public T setDelete(boolean drop) {
        this.drop = drop;
        return (T)this;
    }

    public String getAction() {
        return action;
    }

    public T setAction(String action) {
        this.action = action;
        return (T)this;
    }

    public void drop() {
        this.drop = true;
    }


    public boolean isDrop() {
        return drop;
    }


    public T setDrop(boolean drop) {
        this.drop = drop;
        return (T)this;
    }

    public T setNewName(String newName){
        return setNewName(newName, true, true);
    }

    public T setNewName(String newName, boolean setmap, boolean getmap) {
        if(null == update){
            update(setmap, getmap);
        }
        update.setName(newName);
        return (T)update;
    }

    /**
     * 相关表
     * @param update 是否检测upate
     * @return table
     */
    public Table getTable(boolean update) {
        if(update){
            if(null != table && null != table.getUpdate()){
                return (Table) table.getUpdate();
            }
        }
        return table;
    }

    public void setTable(Table table) {
        this.table = table;
    }

    public String getTableName(boolean update) {
        Table table = getTable(update);
        if(null != table){
            return table.getName();
        }
        return null;
    }

    public T setTable(String table) {
        this.table = new Table(table);
        return (T)this;
    }

    public String getDefinition() {
        if(getmap && null != update){
            return  update.definition;
        }
        return definition;
    }

    public T setDefinition(String definition) {
        if(setmap && null != update){
            ((Trigger)update).definition = definition;
            return (T)this;
        }
        this.definition = definition;
        return (T)this;
    }


    public String getDdl() {
        if(null != ddls && ddls.size()>0){
            return ddls.get(0);
        }
        return null;
    }

    public List<String> getDdls() {
        return ddls;
    }

    public void setDdls(List<String> ddl) {
        this.ddls = ddl;
    }
    public void addDdl(String ddl) {
        if(this.ddls == null){
            this.ddls = new ArrayList<>();
        }
        ddls.add(ddl);
    }
    public List<String> ddls() {
        return ddls;
    }
    public List<String> ddls(boolean init) {
        return ddls;
    }
    public List<String> getDdls(boolean init) {
        return ddls;
    }

    public String ddl() {
        if(null != ddls && ddls.size()>0){
            return ddls.get(0);
        }
        return null;
    }
    public String ddl(boolean init) {
        if(null != ddls && ddls.size()>0){
            return ddls.get(0);
        }
        return null;
    }
    public String getDdl(boolean init) {
        if(null != ddls && ddls.size()>0){
            return ddls.get(0);
        }
        return null;
    }

    public Long getObjectId() {
        return objectId;
    }

    public void setObjectId(Long objectId) {
        this.objectId = objectId;
    }

    public T getUpdate() {
        return update;
    }
    public T setUpdate(T update, boolean setmap, boolean getmap) {
        this.update = update;
        this.setmap = setmap;
        this.getmap = getmap;
        if(null != update) {
            update.update = null;
        }
        return (T)this;
    }
    public T update(){
        return update(true, true);
    }
    public T update(boolean setmap, boolean getmap){
        this.setmap = setmap;
        this.getmap = getmap;
        update = clone();
        update.update = null;
        update.origin = this;
        return update;
    }


    public T clone(){
        T copy = null;
        try {
            copy = (T)getClass().newInstance();
            BeanUtil.copyFieldValue(copy, this);
            copy.update = null;
            copy.setmap = false;
            copy.getmap = false;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return copy;
    }


}
